﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Runtime.Serialization;
using System.Globalization;
using eeenno.ReaderEngine;
using eeenno.ReaderEngine.Utilities;

namespace eeenno.ReaderEngine.Objects
{
    [Serializable]

    /// <summary>
    /// Collection of article objects
    /// </summary>
    public class Articles
    {
        private const char _DATE_TIME_SPLIT = 'T';
        private const char _DATE_SPLIT = '-';
        private const char _TIME_SPLIT = ':';

        public List<Article> _items;
        private string _continuation;

        public Articles()
        {
            _items = new List<Article>(10);           
        }

        public Articles(List<Article> items)
        {
            _items = items;
        }

        public Article Get(string name)
        {
            for (int i = 0; i < Count; i++)
            {
                if (name == _items[i].id)
                    return _items[i];
            }
            return null;
        }

        public Article Get(int index)
        {
            return _items[index];
        }

        public void Sort()
        {
            _items.Sort();
            _items.Reverse();
        }

        public void Add(Article item)
        {
            if (item != null)
            {
                _items.Add(item);
            }
        }

        public void Add(Articles items, bool add_to_end, bool sort)
        {
            if (add_to_end && items != null && items._items != null)
            {
                _items.InsertRange(_items.Count, items._items);
            }
            else if (items != null && items._items != null)
            {
                _items.InsertRange(0, items._items);
            }
            if (sort)
            {
                Sort();
            }
        }

        public int Count
        {
            get
            {
                if (_items != null)
                {
                    return _items.Count;
                }
                else
                {
                    return 0;
                }
            }
        }

        public string continuation
        {
            get { return _continuation; }
            set { _continuation = value; }
        }

        public void MarkAllArticlesRead()
        {
            for (int i = 0; i < Count; i++)
            {
                if (Get(i) != null)
                {
                    Get(i).unread = false;
                }
            }
        }

        public int UnreadCount()
        {
            int ret_val = 0;
            for (int i = 0; i < Count; i++)
            {
                if (Get(i).unread)
                {
                    ret_val++;
                }
            }
            return ret_val;
        }

        public Articles(string[,] article_data)
        {
            if (article_data.Length > 0)
            {
                _items = new List<Article>(10);
                try
                {
                    _continuation = article_data[0, 9];
                }
                catch (IndexOutOfRangeException e)
                {
                }
                Build(article_data);
            }
        }

        public string GetLatestUnixTimeStamp()
        {
            string ret_val = String.Empty;
            Sort();
            if (Count > 0)
            {
                ret_val = Get(0).date;
                ret_val = ConvertDateTimeToUnixTime(ret_val, 1);
            }

            return ret_val;
        }        

        public void Build(string[,] articles)
        {
            for (int i = 0; i < articles.GetLength(0); i++)
            {
                Article article = new Article();
                article.title = FilterSymbols(articles[i, 0]);
                article.long_date = long.Parse(articles[i, 1]);
                article.date = ConvertUnixTimetoDateTime(articles[i, 1]);
                article.id = articles[i, 2];
                article.tag = GetTags(articles[i, 3]);
                article.url = articles[i, 4];
                article.author = FilterSymbols(articles[i, 6]);
                article.unread = GetUnread(article.tag);
                article.starred = GetStarred(article.tag);
                article.site_url = articles[i, 7];
                article.site_name = FilterSymbols(articles[i, 8]);
                article.summary = AddArticleTitle(article.title, article.url) + 
                    AddArticleSiteName(article.site_name) +  "<br />" + article.date + "<br />" +
                    AddArticleAuthor(article.author) + "<br /><br />" + articles[i, 5] + 
                    "<br /><br />";
                article.summary = FilterSymbols(article.summary);
                Add(article);
            }
            Sort();
        }

        private string AddArticleAuthor(string author)
        {
            if (!author.Contains("unknown"))
            {
                return "by " + author;
            }
            return "";
        }

        private string AddArticleSiteName(string sitename)
        {
            return "<b>" + sitename + "</b>";
        }

        private string AddArticleTitle(string title, string link)
        {
            if (Settings.always_use_internal_browser)
            {
                return "<h3><a href=\"" + link + "\">" + title + "</a></h3>";
            }
            else
            {
                return "<h3>" + title + "</h3>";
            }
        }

        private string AddArticleLink(string link)
        {
            return "<h3><a href=\"" + link + "\">Link to article</a></h3>";
        }

        private bool GetUnread(string data)
        {
            data = data.Replace("reading-list", String.Empty);
            if (data.ToLower().Contains("read") && !data.ToLower().Contains("tracking-kept-unread"))
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        private bool GetStarred(string data)
        {
            if (data.ToLower().Contains("starred"))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private string GetTags(string data)
        {
            if (data[0].Equals('~'))
            {
                data = data.Remove(0, 1);
            }
            return data.Replace('~', ',');
        }

        private string FormatBody(string data)
        {
            return data;
        }

        private string FilterSymbols(string input)
        {
            input = input.Replace("&#39;", "'");
            input = input.Replace("&amp;", "&");
            input = input.Replace("&gt;", ">");   
            input = input.Replace("&lt;", "<");    
            input = input.Replace("&quot;", "\"");      
            input = input.Replace("<em>", String.Empty);     
            input = input.Replace("</em>", String.Empty);            
            return input;
        }

        /// <summary>
        /// Parses the data retrieved from Google feed data
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static string ConvertUnixTimetoDateTime(string date)
        {
            int crawl_time = 0;
            try
            {
                crawl_time = (int)(double.Parse(date) / 1000);
            }
            catch (Exception e)
            {
                return String.Empty;
            }
            DateTime datetime = TimeZone.CurrentTimeZone.ToLocalTime(Settings.unix_datetime.AddSeconds(crawl_time));
            return datetime.ToString("g", CultureInfo.CurrentCulture.DateTimeFormat);
        }

        public static string ConvertDateTimeToUnixTime(string date, int additional_min)
        {
            DateTime datetime = new DateTime();
            try
            {
                datetime = TimeZone.CurrentTimeZone.ToUniversalTime(DateTime.Parse(date, CultureInfo.CurrentCulture.DateTimeFormat));
            }
            catch (Exception e)
            {
                datetime = new DateTime();
            }
            datetime = datetime.AddMinutes(additional_min);
            return (datetime - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds.ToString();
        }

        public Articles GetRange(int count)
        {
            return new Articles(_items.GetRange(0, count));
        }
    }
}
